﻿using Admin.Application.DynamicApi.System.Menu;
using Admin.Application.DynamicApi.System.Org;
using Admin.Application.DynamicApi.System.Role.Dto;
using Admin.Application.DynamicApi.System.User;
using Admin.Database.Enums;
using Admin.Database.Model;
using Framework.Core.CustomException;
using Framework.DynamicApiController;
using Framework.SqlSugar;
using Framework.SqlSugar.Repository;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;

namespace Admin.Application.DynamicApi.System.Role
{
	/// <summary>
	/// 角色服务 🧩
	/// </summary>
	[Service]
	public class SysRoleService
	{
		private readonly UserManager _userManager;
		private readonly SqlSugarRepository<SysRole> _sysRoleRep;
		private readonly SysOrgService _sysOrgService;
		private readonly SysMenuService _sysMenuService;
		private readonly SysUserRoleService _sysUserRoleService;
		private readonly SysRoleMenuService _sysRoleMenuService;
		private readonly SysRoleOrgService _sysRoleOrgService;

		public SysRoleService(UserManager userManager,
		   SysOrgService sysOrgService,
		   SysMenuService sysMenuService,
		   SysRoleOrgService sysRoleOrgService,
		   SqlSugarRepository<SysRole> sysRoleRep,
		   SysRoleMenuService sysRoleMenuService,
		   SysUserRoleService sysUserRoleService)
		{
			_userManager = userManager;
			_sysRoleRep = sysRoleRep;
			_sysOrgService = sysOrgService;
			_sysMenuService = sysMenuService;
			_sysRoleOrgService = sysRoleOrgService;
			_sysRoleMenuService = sysRoleMenuService;
			_sysUserRoleService = sysUserRoleService;
		}

		/// <summary>
		/// 获取角色分页列表 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("获取角色分页列表")]
		public async Task<SqlSugarPagedList<SysRole>> Page(PageRoleInput input)
		{
			// 当前用户已拥有的角色集合
			var roleIdList = _userManager.SuperAdmin ? new List<long>() : await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
			return await _sysRoleRep.AsQueryable()
				
				.WhereIF(!_userManager.SuperAdmin, u => roleIdList.Contains(u.Id)) // 若非超管且，则只能操作自己拥有的角色
				.WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
				.WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code))
				.OrderBy(u => new { u.OrderNo, u.Id })
				.ToPagedListAsync(input.Page, input.PageSize);
		}

		/// <summary>
		/// 获取角色列表 🔖
		/// </summary>
		/// <returns></returns>
		[DisplayName("获取角色列表")]
		public async Task<List<RoleOutput>> GetList()
		{
			// 当前用户已拥有的角色集合
			var roleIdList = _userManager.SuperAdmin ? new List<long>() : await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);

			return await _sysRoleRep.AsQueryable()
				.WhereIF(!_userManager.SuperAdmin , u => roleIdList.Contains(u.Id)) // 若非超管且非系统管理员，则只显示已拥有的角色
				.Where(u => u.Status != StatusEnum.Disable) // 非禁用的
				.OrderBy(u => new { u.OrderNo, u.Id }).Select<RoleOutput>().ToListAsync();
		}

		/// <summary>
		/// 增加角色 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[HttpPost]
		[DisplayName("增加角色")]
		public async Task AddRole(AddRoleInput input)
		{
			if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code))
				throw new CustomException("数据已存在");

			var newRole = await _sysRoleRep.AsInsertable(input.Adapt<SysRole>()).ExecuteReturnEntityAsync();
			input.Id = newRole.Id;
			await UpdateRoleMenu(input);
		}

		/// <summary>
		/// 更新角色菜单权限
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		private async Task UpdateRoleMenu(AddRoleInput input)
		{
			if (input.MenuIdList == null || input.MenuIdList.Count < 1) return;
			await GrantMenu(new RoleMenuInput()
			{
				Id = input.Id,
				MenuIdList = input.MenuIdList.ToList()
			});
		}

		/// <summary>
		/// 更新角色 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[HttpPost]
		[DisplayName("更新角色")]
		public async Task UpdateRole(UpdateRoleInput input)
		{
			if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id))
				throw new CustomException("数据已存在");

			await _sysRoleRep.AsUpdateable(input.Adapt<SysRole>()).IgnoreColumns(true)
				.IgnoreColumns(u => new { u.DataScope }).ExecuteCommandAsync();

			await UpdateRoleMenu(input);
		}

		/// <summary>
		/// 删除角色 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[UnitOfWork]
		[HttpPost]
		[DisplayName("删除角色")]
		public async Task DeleteRole(DeleteRoleInput input)
		{
			// 若角色有用户则禁止删除
			var userIds = await _sysUserRoleService.GetUserIdList(input.Id);
			if (userIds != null && userIds.Count > 0) throw new CustomException("此角色下面存在账号禁止删除");
			
			var sysRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id) ?? throw new CustomException("记录不存在");
			await _sysRoleRep.DeleteAsync(sysRole);

			// 级联删除角色机构数据
			await _sysRoleOrgService.DeleteRoleOrgByRoleId(sysRole.Id);

			// 级联删除用户角色数据
			await _sysUserRoleService.DeleteUserRoleByRoleId(sysRole.Id);

			// 级联删除角色菜单数据
			await _sysRoleMenuService.DeleteRoleMenuByRoleId(sysRole.Id);
		}

		/// <summary>
		/// 授权角色菜单 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[UnitOfWork]
		[DisplayName("授权角色菜单")]
		public async Task GrantMenu(RoleMenuInput input)
		{
			await _sysRoleMenuService.GrantRoleMenu(input);
		}

		/// <summary>
		/// 授权角色数据范围 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[UnitOfWork]
		[DisplayName("授权角色数据范围")]
		public async Task GrantDataScope(RoleOrgInput input)
		{
			// 删除与该角色相关的用户机构缓存
			var userIdList = await _sysUserRoleService.GetUserIdList(input.Id);
			foreach (var userId in userIdList)
			{
				SqlSugarFilter.DeleteUserOrgCache(userId, _sysRoleRep.Context.CurrentConnectionConfig.ConfigId.ToString());
			}

			var role = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
			var dataScope = input.DataScope;
			if (!_userManager.SuperAdmin)
			{
				switch (dataScope)
				{
					// 非超级管理员没有全部数据范围权限
					case (int)DataScopeEnum.All: throw new CustomException("没有权限");
					// 若数据范围自定义，则判断授权数据范围是否有权限
					case (int)DataScopeEnum.Define:
						{
							var grantOrgIdList = input.OrgIdList;
							if (grantOrgIdList.Count > 0)
							{
								var orgIdList = await _sysOrgService.GetUserOrgIdList();
								if (orgIdList.Count < 1)
									throw new CustomException("没有权限");
								if (!grantOrgIdList.All(u => orgIdList.Any(c => c == u)))
									throw new CustomException("没有权限");
							}

							break;
						}
				}
			}
			role.DataScope = (DataScopeEnum)dataScope;
			await _sysRoleRep.AsUpdateable(role).UpdateColumns(u => new { u.DataScope }).ExecuteCommandAsync();
			await _sysRoleOrgService.GrantRoleOrg(input);
		}

		/// <summary>
		/// 根据角色Id获取菜单Id集合 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("根据角色Id获取菜单Id集合")]
		public async Task<List<long>> GetOwnMenuList([FromQuery] RoleInput input)
		{
			var menuIds = await _sysRoleMenuService.GetRoleMenuIdList(new List<long> { input.Id });
			return await _sysMenuService.ExcludeParentMenuOfFullySelected(menuIds);
		}

		/// <summary>
		/// 根据角色Id获取机构Id集合 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("根据角色Id获取机构Id集合")]
		public async Task<List<long>> GetOwnOrgList([FromQuery] RoleInput input)
		{
			return await _sysRoleOrgService.GetRoleOrgIdList(new List<long> { input.Id });
		}

		/// <summary>
		/// 设置角色状态 🔖
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		[DisplayName("设置角色状态")]
		public async Task<int> SetStatus(RoleInput input)
		{
			if (!Enum.IsDefined(typeof(StatusEnum), input.Status)) throw new CustomException("字典状态错误");

			return await _sysRoleRep.AsUpdateable()
				.SetColumns(u => u.Status == input.Status)
				.Where(u => u.Id == input.Id)
				.ExecuteCommandAsync();
		}
	}
}
